package adminlte.config;

import adminlte.service.BaseUserDetailService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 *  spring-security安全配置， 初始化流程参见父类{@link WebSecurityConfigurerAdapter}
 * @author ZHUFEIFEI
 */
@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //配置用户信息加载服务类
        auth.userDetailsService(new BaseUserDetailService());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //静态资源忽略安全认证
        web.ignoring().antMatchers("/static/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置访问规则，使用默认规则，允许表单登陆和http basic，并且所有请求需要登陆
        super.configure(http);
    }

    /**
     * userDetailsServiceBean 返回UserDetailsService一个代理，该代理实际是
     * 从AuthenticationManagerBuilder中获取defaultUserDetailsService,
     * 就是方法 configure(AuthenticationManagerBuilder auth) 配置的userDetailsService,
     * 此处作为bean暴露，是用于OAuth2配置类
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return super.userDetailsServiceBean();
    }

    /**
     * 返回认证管理bean的代理，该管理类用于用户名密码认证，结合OAuth2
     * 提供给OAuth2做密码认证管理,
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 创建明文密码加密解密工具bean, 在本类初始化完成后会在ApplicationContext中
     * 查找可用的PasswordEncoder对象用于密码验证和加密。
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

}
